#pragma once
#include "DPlane.h"
#include "../DSpace.h"
#include "../DVector3.h"
#include "../DVector4.h"

namespace Skill
{
	namespace Ode
	{		
		namespace Geometries
		{
			void DPlane::CollectManagedMemory()
			{
				_Normal = nullptr;
				DGeometry::CollectManagedMemory();
			}
			DPlane::DPlane(DSpace^ space, dReal a, dReal b, dReal c, dReal d)
				:DGeometry(space)
			{		
				dSpaceID s = space?space->_Space() : NULL;
				_SetPointer(dCreatePlane(s,a,b,c,d),true);	
				if(_Container)
						_Container->AddSpace(this);
			}

			DPlane::DPlane(DSpace^ space, DVector3^ normal , dReal d)
				:DGeometry(space)
			{		
				dSpaceID s = space?space->_Space() : NULL;
				_SetPointer(dCreatePlane(s,normal->_This[0],normal->_This[1],normal->_This[2],d),true);	
				if(_Container)
						_Container->AddSpace(this);
			}

			DVector4^ DPlane::Normal::get()
			{
				if(IsSpace) return nullptr;
				if(!_Normal)
					_Normal = gcnew DVector4();
				dGeomPlaneGetParams(_Geom(),_Normal->_This);
				return _Normal;
			}
			void DPlane::Normal::set(DVector4^ value)
			{				
				if(IsSpace) return;
				dGeomPlaneSetParams(_Geom(),value->_This[0],value->_This[1],value->_This[2],value->_This[3]);
			}
			dReal DPlane::D::get()
			{
				if(IsSpace) return Single::NaN;
				if(!_Normal)
					_Normal = gcnew DVector4();
				dGeomPlaneGetParams(_Geom(),_Normal->_This);
				return _Normal->_This[3];
			}
			void DPlane::D::set(dReal value)
			{
				if(IsSpace) return;
				if(!_Normal)
					_Normal = gcnew DVector4();
				dGeomPlaneGetParams(_Geom(),_Normal->_This);
				_Normal->_This[3] = value;
				dGeomPlaneSetParams(_Geom(),_Normal->_This[0],_Normal->_This[1],_Normal->_This[2],_Normal->_This[3]);
			}

			void DPlane::SetParams(dReal a, dReal b, dReal c, dReal d)
			{
				if(IsSpace) return;
				dGeomPlaneSetParams(_Geom(),a,b,c,d);
			}
			void DPlane::SetParams(DVector3^ normal, dReal d)
			{
				if(IsSpace) return;
				dGeomPlaneSetParams(_Geom(),normal->_This[0],normal->_This[1],normal->_This[2],d);
			}
			void DPlane::SetParams(DVector4^ normalAndD)
			{
				if(IsSpace) return;
				dGeomPlaneSetParams(_Geom(),normalAndD->_This[0],normalAndD->_This[1],normalAndD->_This[2],normalAndD->_This[3]);
			}

			dReal DPlane::PointDepth(dReal x, dReal y, dReal z)
			{
				if(IsSpace) return Single::NaN;
				return dGeomPlanePointDepth(_Geom(),x,y,z);
			}
			dReal DPlane::PointDepth(DVector3^ p)
			{
				if(IsSpace) return Single::NaN;
				return dGeomPlanePointDepth(_Geom(),p->_This[0],p->_This[1],p->_This[2]);
			}
		}
	}
}